home *** CD-ROM | disk | FTP | other *** search
- //• SolverPPC1_1.c
- //• ©1995 by Stefan C. Sinclair - All rights reserved.
- /* This source code is a stripped down but heavily commented version of my shareware program
- Solver 1.1 . The complete program is available elsewhere in AOL (Utilities Programs,
- Education Programs - well worth the download!).
- I have included all the code I used for it here, minus the routines
- that perform the mathematical computations (that's my secret!).
- These files show how to:
- a) Support simple text editing in a dialog.
- b) Use simple PICT resources for buttons in a dialog - pretty slick trick I discovered.
- c) Support standard Edit Menu items such as Cut, Copy, Paste, Select All, Clear, and Undo.
- d) demonstrates how to use scroll bars to scroll a large picture in a window
- e) Display numbers in standard or exponential notation depending on their size
- f) Use PowerPC Procedures
- g) Simple error handling
- h) Put an easter egg in your program - cool!
- The included files were compiled with
- Symantec C++ v8.0.3, but with very little modification,
- they can be made to compile 68K Mac code (I used THINK C v7 for this).
- To make a project from these files, add the following files to your project:
- - SolverPPC1_1.c -> demonstrates how to use a modeless dialog in your application.
- Modeless dialogs are much friendlier to the user than modal dialogs.
- - Help.c -> for online help
- - SolverDemo.π.rsrc
- - ANSI C function library
- - Mac Function Library (these will vary depending on the compiler you are using)
-
- The methods I use are probably not the best, but they get the job done (more or less). I hope
- people will find this helpful - I know I would have a couple years back when I was just starting
- to program on the Mac! Let me know if you find this helpful; I would also be glad to answer any questions
- you might have on this source code. You can reach me via e-mail at: trickys@aol.com
- */
-
- #include <math.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <EPPC.h>
- #include <GestaltEqu.h>
- #include <AppleEvents.h>
- #include <Values.h>
- #include <Dialogs.h>
-
- #define kBaseResID 128
-
- #define kMaxNameLength 50 //• Used for registering the shareware app
- #define kMinNameLength 12 //• Used for registering the shareware app
- #define kPleaseRegisterAlertNum 131
- #define kRegistrationDLOG 132
-
- #define kMinTextPosition 0
- #define kMaxTextPosition 32767
-
- #define kMoveToFront (WindowPtr)-1L
- #define kSleep 3600L
- #define kLeaveWhereItIs false
- #define kUseDefaultProc (void *) -1L
- #define kMinTextPosition 0
- #define kMaxTextPosition 32767
- #define kNilSoundChannel nil
- #define kSynchronous false
- #define kGestaltMask 1L
- #define kPrecision 17 //• Maximum precision displayed after calculations
- #define kUseExponentialNotation 9 //• How big the number gets before exponential notation is used
- #define kPI 3.141592653589793
-
- //• Globals
- Boolean gDone = false, gRegistered=false, gSave = false, gRad = true;
- MenuHandle gMenu;
- DialogPtr dialog;
- short itemHit, itemType, vRefNum;
- Handle textItemHandle;
- Handle itemHandle;
- Handle okItemHandle;
- Handle expTextH;
- Handle invTextH;
- Handle ansTextH;
- Rect itemRect;
- Str255 expressionStr="\p", saveStr = "\p";
- Str63 memStr = "\p", answerStr="\p";
- FILE *cfPtr;
- Str255 name;
-
- Rect helpRect;
- PicHandle helpPicture;
- WindowPtr hwindow;
-
- //• Function Prototypes
- void AEInstallHandlers(void);
- pascal OSErr DoOpenApp( AppleEvent *event, AppleEvent *reply, long refcon);
- pascal OSErr DoOpenDoc( AppleEvent *event, AppleEvent *reply, long refcon);
- pascal OSErr DoPrintDoc( AppleEvent *event, AppleEvent *reply, long refcon);
- pascal OSErr DoQuitApp( AppleEvent *event, AppleEvent *reply, long refcon);
- OSErr CheckForRequiredParams( AppleEvent *event);
- void ToolboxInit(void);
- void MenuBarInit(void);
- void AEInit(void);
- void DoUpdate(EventRecord *eventPtr);
- void DoError( Str255 errorString, Boolean fatal);
- void HandleMenuChoice( long menuChoice);
- void HandleAppleChoice( short item);
- void HandleFileChoice( short item);
- void DoMainDLOG(void);
- void DoEvent( EventRecord *eventPtr);
- void HandleMouseDown( EventRecord *eventPtr);
- void TypeIt(char c);
- void BackIBeam(void);
- void HandleEditChoice( short item);
- void Credits(void);
- short isPressed(unsigned short k ); //• From THINK Reference
- Boolean ThisButton(EventRecord *ep, Rect *r);
- short doDlgEvt(EventRecord *evp);
- void pStrCopy(StringPtr p1, StringPtr p2);
-
- /* More Function prototypes */
- double Solve(char infixStr[]);
- void EmptyString(char *string, short num);
- void SaveNew(void);
- void Registration(void);
- Boolean isRegistered(void);
- void PleaseRegister(void);
- void Help(void);
-
- pascal OSErr SetDialogDefaultItem(DialogPtr theDialog, short item)
- = { 0x303C, 0x0304, 0xAA68};
- pascal OSErr SetDialogCancelItem(DialogPtr theDialog, short item)
- = {0x303C, 0x0305, 0xAA68};
- pascal OSErr SetDialogTracksCursor(DialogPtr theDialog, Boolean tracks)
- = {0x303C, 0x0306, 0xAA68};
-
- main()
- {
- OSErr err;
- FInfo fndrInfo;
-
- ToolboxInit();
- AEInit(); //• Support the required Apple Events - very important!
- //• gRegistered = isRegistered();
- gRegistered = false; //• for this demo's purposes.
- if(!gRegistered)
- {
- PleaseRegister();
- if(gRegistered)
- DoError("\pYou are now a registered user!", false);
- }
-
- MenuBarInit();
- //• Next, load the Help window, but don't show it until needed.
- if ( ( hwindow = GetNewWindow( kBaseResID, nil,
- kMoveToFront ) ) == nil )
- DoError( "\pCan't Load WIND resource!", true );
- //• Online help consists of a very tall PICT
- if ( ( helpPicture = (PicHandle)GetResource( 'PICT', 150) ) == nil )
- DoError( "\pCan't Load Help PICT resource!", true );
- //• helpRect is set to the actual size of the PICT
- helpRect.top = hwindow->portRect.top + 2;
- helpRect.left = hwindow->portRect.left + 2;
- helpRect.right = helpRect.left + 313;
- helpRect.bottom = helpRect.top + 812;
- //• Set up help window scroll bars
- SetUpScrollBar( hwindow );
- //• Enter main program
- if(!gDone)
- DoMainDLOG();
- /* DoMainDLOG will get called more later on. The strategy I employ here is to exit and dispose of
- the main dialog every time some other dialog or alert is brought up. Afterwards, DoMainDLOG() is
- called again. Sort of strange, but it works pretty good. */
- DisposeDialog(dialog); //• Here we are done for good
- if(!gRegistered)
- PleaseRegister();
- //• In registered versions, the output gets saved to a TeachText file if desired - pretty usefull.
- if(gSave)
- {
- fclose(cfPtr);
- err = GetFInfo(name,vRefNum,&fndrInfo);
- if(err)
- SysBeep(30);
- fndrInfo.fdType = 'TEXT';
- fndrInfo.fdCreator = 'ttxt';
- err = SetFInfo(name,vRefNum,&fndrInfo);
- if(err)
- SysBeep(30);
- }
- return 0; //• All finished.
- }
-
- //• ToolboxInit() - pretty straight forward
- void ToolboxInit()
- {
- InitGraf((Ptr) &qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- FlushEvents(everyEvent,0);
- TEInit();
- InitDialogs(0L);
- InitCursor();
- }
-
- //• MenuBarInit() - pretty straight forward
- void MenuBarInit( void)
- {
- Handle menuBar;
-
- menuBar = GetNewMBar(128);
- SetMenuBar( menuBar);
-
- gMenu = GetMenu( 128); // apple
- AddResMenu( gMenu, 'DRVR');
-
- gMenu = GetMenu( 129); // File
- InsertMenu( gMenu, -1);
- if(!gRegistered)
- DisableItem(gMenu, 1);
-
- gMenu = GetMenu( 130); // Edit
- InsertMenu( gMenu, -1);
-
- DrawMenuBar();
- }
-
- //• AEInit() - pretty straight forward
- void AEInit( void)
- {
- OSErr err;
- long feature;
-
- err = Gestalt(gestaltAppleEventsAttr, &feature);
- if(err != noErr)
- DoError("\pError returned by gestalt!", true);
- if(!(feature & (kGestaltMask << gestaltAppleEventsPresent)))
- DoError("\pApple Events not supported!", true);
- AEInstallHandlers();
- }
-
- //• AEInstallHandlers() - this version is written for compiling PPC native code
- void AEInstallHandlers(void)
- {
- OSErr err;
- /* install the required apple event handlers */
- AEEventHandlerUPP OPENae, QUITae, STARTae, PRINTae;
-
- /* must use these for PPC proc pointers */
- OPENae = NewAEEventHandlerProc ((ProcPtr) &DoOpenDoc);
- QUITae = NewAEEventHandlerProc ((ProcPtr) &DoQuitApp);
- STARTae = NewAEEventHandlerProc ((ProcPtr) &DoOpenApp);
- PRINTae = NewAEEventHandlerProc ((ProcPtr) &DoPrintDoc);
- err = AEInstallEventHandler( kCoreEventClass, kAEOpenApplication,STARTae, 0L, false);
- if(err != noErr)
- DoError("\pError installing 'open app' handler!", true);
- err = err = AEInstallEventHandler( kCoreEventClass, kAEOpenDocuments, OPENae, 0L, false);
- if(err != noErr)
- DoError("\pError installing 'open doc' handler!", true);
- err = err = AEInstallEventHandler( kCoreEventClass, kAEPrintDocuments, PRINTae, 0L, false);
- if(err != noErr)
- DoError("\pError installing 'print doc' handler!", true);
- err = err = AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, QUITae, 0L, false);
- if(err != noErr)
- DoError("\pError installing 'quit app' handler!", true);
- }
-
- pascal OSErr DoOpenApp( AppleEvent *event, AppleEvent *reply, long refcon)
- {
- //• Do nothing. Normally, you might open a new Untitled window or something.
- return noErr;
- }
-
- pascal OSErr DoOpenDoc( AppleEvent *event, AppleEvent *reply, long refcon)
- {
- //• Again nothing will ever happen (this routine won't get called in this program, but it's still helpful to read)
- OSErr err;
- FSSpec fileSpec;
- long i, numDocs;
- DescType returnedType;
- AEKeyword keywd;
- Size actualSize;
- AEDescList docList = {typeNull, nil}; // Get the direct parameter-a descriptor list-and put into docList
-
- err = AEGetParamDesc(event, keyDirectObject, typeAEList, &docList);
- err = CheckForRequiredParams( event); // Check for missing required parameters
- if(err)
- {
- err = AEDisposeDesc( &docList);
- return err;
- }
- err = AECountItems( &docList, &numDocs); // Count #of descriptor records in the list
- if(err) // Should be at least 1 since we got called & no error.
- {
- err = AEDisposeDesc( &docList);
- return err;
- }
- // Now get each descriptor record, coerce data to an FSSpec record, & open the file
- for( i = 1; i <= numDocs; i++)
- {
- err = AEGetNthPtr( &docList, i, typeFSS, &keywd, &returnedType, (Ptr)&fileSpec, sizeof(fileSpec), &actualSize);
- //OpenDocument( &fileSpec); <- normally would do something like this
- //• See above! DoMainDLOG();
- }
- err = AEDisposeDesc( &docList);
- return err;
- }
-
-
- OSErr CheckForRequiredParams( AppleEvent *appleEventPtr)
- {
- DescType returnedType;
- Size actualSize;
- OSErr err;
-
- err = AEGetAttributePtr( appleEventPtr, keyMissedKeywordAttr, typeWildCard, &returnedType, nil, 0, &actualSize);
- //• Looks for specified attribute, returns attribute status as an error
-
- if( err == errAEDescNotFound)
- return noErr;
- else if( err == noErr)
- return errAEParamMissed;
- else
- return err;
- }
-
- pascal OSErr DoPrintDoc( AppleEvent *event, AppleEvent *reply, long refcon)
- {
- return noErr;
- }
-
- pascal OSErr DoQuitApp( AppleEvent *event, AppleEvent *reply, long refcon)
- {
- gDone = true;
- return noErr;
- }
-
- /********** DoError ********************/
- /* Pretty simple. Should probably check to make sure that Alert #128 is really present, though*/
- void DoError( Str255 errorString, Boolean fatal)
- {
- ParamText( errorString, "\p", "\p", "\p");
- NoteAlert( 128, nil);
- if( fatal == true)
- ExitToShell();
- }
-
- //• pStrCopy()
- void pStrCopy (StringPtr p1, StringPtr p2)
- /* copies a pascal string from p1 to p2 . "Borrowed" from THINK Reference*/
- {
- register int len;
-
- len = *p2++ = *p1++;
- while (--len >= 0)
- *p2++ = *p1++;
- }
-
- //• HandleMenuChoice()
- void HandleMenuChoice( long menuChoice)
- {
- short menu;
- short item;
-
- if( menuChoice != 0)
- {
- menu = HiWord( menuChoice);
- item = LoWord( menuChoice);
- switch( menu)
- {
- case 128: // apple
- HandleAppleChoice( item);
- break;
- case 129: // File
- HandleFileChoice( item);
- break;
- case 130:
- HandleEditChoice(item);
- break;
- }
- HiliteMenu(0);
- }
- }
-
- //• HandleAppleChoice
- void HandleAppleChoice( short item)
- {
- MenuHandle appleMenu;
- Str255 accName;
- short accNumber;
-
- switch( item)
- {
- case 1:
- Credits(); //• All about my wonderful program
- break;
- default:
- appleMenu = GetMHandle( 128);
- GetItem( appleMenu, item, accName);
- accNumber = OpenDeskAcc( accName);
- break;
- }
- }
-
- //• HandleFileChoice()
- void HandleFileChoice( short item)
- {
- switch( item)
- {
- case 1: // Save to file - available only to registered users
- if(!gSave)
- {
- gSave = true;
- SaveNew();
- }
- break;
- case 3: // Quit
- gDone = true;
- break;
- default:
- break;
- }
- }
-
- //• SaveNew()
- void SaveNew(void)
- {
- OSErr err;
- SFReply theFile;
- short i, ie, k, fRefNum;
- Point where; /* where to display dialog */
-
- /* Many of the File Creating & Writing Routines used here are
- specific to the Macintosh */
- if(gRegistered)
- {
- where.h = 20;
- where.v = 20;
- SFPutFile(where, "\pSave Solver output as: ", "\pUntitled", nil, &theFile);
- if (!theFile.good)
- DoError("\pError creating new file.", true);
- vRefNum = theFile.vRefNum;
- err = Create(theFile.fName, theFile.vRefNum, 'ttxt', 'TEXT');
- if(err)
- DoError("\pError creating the new file.", true);
- err = SetVol(NULL, theFile.vRefNum);
- pStrCopy(theFile.fName, name);
- if (err)
- DoError("\pCould not Set Volume.", true);
- cfPtr = fopen (p2cstr(name), "w");
- if (cfPtr == NULL)
- DoError("\pCan't open the new file.", true);
- c2pstr((char *)name); //• Don't forget to convert back to a Pascal string!
- }
- else
- SysBeep(30);
- }
-
- //• HandleEditChoice()
- void HandleEditChoice( short item)
- {
- short i;
-
- switch( item)
- {
- case 1: // Undo
- GetDItem( dialog, 18, &itemType, &expTextH, &itemRect);
- GetIText( expTextH, expressionStr);
- SetIText(expTextH, saveStr);
- //• save current entry in 'saveStr' in case user wants to 'Undo' later on.
- //• That is how the Undo function is supported.
- for(i=0; i<255; i++)
- saveStr[i] = expressionStr[i];
- break;
- case 3: // Cut - made very easy in a dialog
- GetDItem( dialog, 18, &itemType, &expTextH, &itemRect);
- GetIText( expTextH, expressionStr);
- //• save current entry in case user wants to 'Undo' later on.
- for(i=0; i<255; i++)
- saveStr[i] = expressionStr[i];
- DlgCut(dialog);
- break;
- case 4: // Copy
- DlgCopy(dialog);
- break;
- case 5: // Paste
- GetDItem( dialog, 18, &itemType, &expTextH, &itemRect);
- GetIText( expTextH, expressionStr);
- //• save current entry in case user wants to 'Undo' later on.
- for(i=0; i<255; i++)
- saveStr[i] = expressionStr[i];
- DlgPaste(dialog);
- break;
- case 6: // Clear
- GetDItem( dialog, 18, &itemType, &expTextH, &itemRect);
- GetIText( expTextH, expressionStr);
- //• save current entry in case user wants to 'Undo' later on.
- for(i=0; i<255; i++)
- saveStr[i] = expressionStr[i];
- DlgDelete(dialog);
- break;
- case 8: //• Select All
- SelIText( dialog, 18, kMinTextPosition, kMaxTextPosition);
- break;
- }
- }
-
-
- //• DoMainDLOG()
- void DoMainDLOG(void)
- {
- EventRecord event;
- Boolean evtOccured;
- short i=0;
- char cStr[256] = "";
-
- dialog = GetNewDialog(133, nil, kMoveToFront);
- SetPort(dialog);
- ShowWindow(dialog);
-
- GetDItem( dialog, 17, &itemType, &okItemHandle, &itemRect);
- GetDItem( dialog, 18, &itemType, &expTextH, &itemRect);
- //SelIText( dialog, 18, kMinTextPosition, kMaxTextPosition);
- GetDItem( dialog, 19, &itemType, &ansTextH, &itemRect);
- GetDItem( dialog, 20, &itemType, &itemHandle, &itemRect);
- GetDItem( dialog, 21, &itemType, &itemHandle, &itemRect);
- GetDItem( dialog, 22, &itemType, &itemHandle, &itemRect);
-
- SetDialogTracksCursor(dialog, true);
-
- //• There may be something stored in 'saveStr[]', as this routine will usually get called several times.
- GetDItem( dialog, 18, &itemType, &expTextH, &itemRect);
- GetIText( expTextH, expressionStr);
- SetIText(expTextH, "\p");
- strcpy(cStr, p2cstr(saveStr));
- while(cStr[i] != '\0')
- TypeIt(cStr[i++]);
- c2pstr((char *)saveStr); //• Don't forget to change it back!
-
-
-
- while( !gDone)
- {
- evtOccured = GetNextEvent( everyEvent, &event);
- if (evtOccured)
- {
- /* Important to save this first, in case dialog is disposed of and then created again */
- GetDItem( dialog, 18, &itemType, &expTextH, &itemRect);
- GetIText( expTextH, expressionStr);
-
- switch ( event.what )
- {
- case mouseDown:
- HandleMouseDown(&event);
- break;
- case updateEvt:
- DoUpdate(&event);
- break;
- case kHighLevelEvent:
- AEProcessAppleEvent(&event);
- break;
- /* ... process non-dialog events ... */
-
- } /* end of switch */
- if ( IsDialogEvent( &event) )
- doDlgEvt( &event );
- } /* end of if */
- //• Adding this line causes the I-beam to flash as expected
- else if(IsDialogEvent(&event))
- doDlgEvt( &event );
-
- } /* end of while */
- }
-
- /* CODE EXAMPLE #1 - again from THINK Reference */
- short isPressed(unsigned short k )
- // k = any keyboard scan code, 0-127
- {
- unsigned char km[16];
-
- GetKeys( (long *) km);
- return ( ( km[k>>3] >> (k & 7) ) & 1);
- }
-
- //• ThisButton() - checks to see if the button in my main dialog gets pressed.
- Boolean ThisButton(EventRecord *ep, Rect *r)
- {
- Point newPoint, oldPoint;
-
- newPoint = oldPoint = ep->where;
- InvertRect(r); //• My buttons are really just PICTs in the DITL, with the 'Enabled'
- //• Box checked - that is a little trick I discovered by accident. Checking the Enabled box
- //• in the DITL resource lets you detect events in those items! Cool.
- while(WaitMouseUp())
- {
- GetMouse(&newPoint);
- if(DeltaPoint(oldPoint, newPoint))
- ;
- }
- InvertRect(r); //• Put it back to normal
- return(PtInRect(newPoint, r) ? true : false);
- }
-
- //• doDlgEvt() - my main event handling routine. Many of the variables you see
- //• don't get used in this demo source code though. This routine is the guts of the program interface.
- short doDlgEvt(EventRecord *evp)
- {
- DialogPtr whichDlg;
- WindowPtr whichWindow;
- Handle itemH;
- short thePart, k=0, accountForNegative=0, exponent=0;
- char theKey;
- long integer, fraction;
- long i=0, decimalPlace[kPrecision] = {0};
- double dInteger, dFraction, dDecimal, portion;
- double theAnswer = 0, dj=0, log10Answer = 0;
- Str255 pStr1, pStr2, EmptyStr = "\p";
- char cStr1[256], cStr2[256];
- char decimal[] = ".", E[] = "E", minusSign[] = "-", plusSign[] = "+";
- Point oldPoint;
-
- if ( evp->what == keyDown )
- {
- if ( evp->modifiers & cmdKey )
- { /*command key pressed - handle accordingly. */
- theKey = evp->message & charCodeMask;
- if( (theKey == 'Z') || (theKey == 'z') )
- HandleEditChoice(1);
- else if( (theKey == 'C') || (theKey == 'c') )/* do command-C via DlgCopy */
- HandleEditChoice(4);
- else if( (theKey == 'X') || (theKey == 'x') )/* do command-X via DlgCut */
- HandleEditChoice(3);
- else if( (theKey == 'V') || (theKey == 'v') )/* do command-V via DlgPaste */
- HandleEditChoice(5);
- else if( (theKey == 'A') || (theKey == 'a') )/* do command-A */
- HandleEditChoice(8);
- else if( (theKey == 'Q') || (theKey == 'q') )/* do command-Q */
- gDone = true;
-
- /*.. here one would check for and process other command-shifted keys if needed ... */
-
- return(0);
- /* the moral here is that you don't let unwanted command-keys into DialogSelect() */
- }
- }
-
- if (DialogSelect( evp, &whichDlg, &itemHit ) == FALSE ) //• Nothing was hit.
- return(0); /* no extra work needed , just return */
-
- if ( whichDlg == dialog && itemHit != 0)
- { /* process the interaction */
- GetDItem( dialog, itemHit, &itemType, &itemH, &itemRect);
- switch(itemHit)
- {
- case 1://• ABS
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- TypeIt('a');
- TypeIt('b');
- TypeIt('s');
- BackIBeam();
- }
- break;
- case 2: //• COS
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- TypeIt('c');
- TypeIt('o');
- TypeIt('s');
- BackIBeam();
- }
- break;
- case 3: //• SIN
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- TypeIt('s');
- TypeIt('i');
- TypeIt('n');
- BackIBeam();
- }
- break;
- case 4: //• TAN
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- TypeIt('t');
- TypeIt('a');
- TypeIt('n');
- BackIBeam();
- }
- break;
- case 5: //• COSH
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- TypeIt('c');
- TypeIt('o');
- TypeIt('s');
- TypeIt('h');
- BackIBeam();
- }
- break;
- case 6: //• SINH
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- TypeIt('s');
- TypeIt('i');
- TypeIt('n');
- TypeIt('h');
- BackIBeam();
- }
- break;
- case 7: //• TANH
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- TypeIt('t');
- TypeIt('a');
- TypeIt('n');
- TypeIt('h');
- BackIBeam();
- }
- break;
- case 8: //• ACOS
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- TypeIt('a');
- TypeIt('c');
- TypeIt('o');
- TypeIt('s');
- BackIBeam();
- }
- break;
- case 9: //• ASIN
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- TypeIt('a');
- TypeIt('s');
- TypeIt('i');
- TypeIt('n');
- BackIBeam();
- }
- break;
- case 10: //• ATAN
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- TypeIt('a');
- TypeIt('t');
- TypeIt('a');
- TypeIt('n');
- BackIBeam();
- }
- break;
- case 11: //• EXP
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- TypeIt('e');
- TypeIt('x');
- TypeIt('p');
- BackIBeam();
- }
- break;
- case 12: //• LN
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- TypeIt('l');
- TypeIt('n');
- BackIBeam();
- }
- break;
- case 13: //• LOG
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- TypeIt('l');
- TypeIt('o');
- TypeIt('g');
- BackIBeam();
- }
- break;
- case 14: //• SQRT
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- TypeIt('s');
- TypeIt('q');
- TypeIt('r');
- TypeIt('t');
- BackIBeam();
- }
- break;
- case 15: //• π
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- TypeIt('3');
- TypeIt('.');
- TypeIt('1');
- TypeIt('4');
- TypeIt('1');
- TypeIt('5');
- TypeIt('9');
- TypeIt('2');
- TypeIt('6');
- TypeIt('5');
- TypeIt('4');
- }
- break;
- case 16: //• e
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- TypeIt('2');
- TypeIt('.');
- TypeIt('7');
- TypeIt('1');
- TypeIt('8');
- TypeIt('2');
- TypeIt('8');
- TypeIt('1');
- TypeIt('8');
- TypeIt('2');
- TypeIt('8');
- }
- break;
- case 17: //• Evaluate
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- GetDItem( dialog, 18, &itemType, &expTextH, &itemRect);
- GetIText( expTextH, expressionStr);
- GetDItem( dialog, 19, &itemType, &ansTextH, &itemRect);
- strcpy(cStr1,p2cstr(expressionStr));
- if(cStr1[0] == '\0')
- {
- cStr1[0] = '0';
- cStr1[1] = '\0';
- }
- theAnswer = Solve(cStr1); //• This routine is my trade secret!
- if(gSave)
- fprintf(cfPtr, "%s =\n", cStr1);
- /* I'm sure there is probably a better way to do this, but this is all I could
- come up with... */
- log10Answer = log10(fabs(theAnswer));
- for(i=0; i<=255; i++)
- cStr1[1] = 0;
- cStr1[0] = '\0';
- /* make sure negative sign stays there */
- if(theAnswer < 0)
- {
- cStr1[0] = '-';
- cStr1[1] = '\0';
- accountForNegative = 1;
- }
- //••• Do we need exponential notation? •••
- exponent = 0 + fabs(log10Answer);
- if(exponent >= kUseExponentialNotation)
- {
- if(log10Answer < 0) //• Negative exponent?
- {
- //• use next 'smallest' integer, and it's negative.
- exponent = 0 - floor(log10Answer);
- theAnswer = theAnswer*pow(10, exponent);//••• theAnswer IS CHANGED!
- }
- else
- theAnswer = theAnswer/pow(10, exponent);//••• theAnswer IS CHANGED!
- dFraction = fabs(modf(theAnswer, &dInteger));
- integer = 0 + fabs(dInteger);
- NumToString(integer, pStr1);
- strcat(cStr1, p2cstr(pStr1));
- k = strlen(cStr1) - accountForNegative;
- strcat(cStr1, decimal);
- /* now add maximum possible decimal places - as acurate as it gets now! */
- dj = 10;
- for(i=0; i< (kPrecision-k); i++)
- {
- decimalPlace[i] = floor(dFraction * dj);
- /* subtract off the 'enlarged' portion */
- dDecimal = decimalPlace[i];
- portion = dDecimal / dj;
- dFraction -= portion;
- NumToString(decimalPlace[i], pStr2);
- strcpy(cStr2, p2cstr(pStr2));
- strcat(cStr1, cStr2);
- dj*=10;
- }
- NumToString(exponent, pStr1);
- strcat(cStr1, E);
- if(log10Answer < 0)
- strcat(cStr1, minusSign);
- else
- strcat(cStr1, plusSign);
- strcat(cStr1, p2cstr(pStr1));
- pStrCopy(c2pstr(cStr1), answerStr); /* answer, w/ E+/- */
- SetIText(ansTextH, answerStr);
- if(gSave)
- {
- fprintf(cfPtr, "\t%s\n", p2cstr(answerStr));
- }
- }
- else //• No exponential notation
- {
- dFraction = fabs(modf(theAnswer, &dInteger));
- integer = 0 + fabs(dInteger);
- NumToString(integer, pStr1);
- strcat(cStr1, p2cstr(pStr1));
- k = strlen(cStr1) - accountForNegative;
- strcat(cStr1, decimal);
- /* now add maximum possible decimal places - as acurate as it gets now! */
- dj = 10;
- for(i=0; i< (kPrecision-k); i++)
- {
- decimalPlace[i] = floor(dFraction * dj);
- /* subtract off the 'enlarged' portion */
- dDecimal = decimalPlace[i];
- portion = dDecimal / dj;
- dFraction -= portion;
- NumToString(decimalPlace[i], pStr2);
- strcpy(cStr2, p2cstr(pStr2));
- strcat(cStr1, cStr2);
- dj*=10;
- }
- pStrCopy(c2pstr(cStr1), answerStr); /* answer! */
- SetIText(ansTextH, answerStr);
- if(gSave)
- {
- fprintf(cfPtr, "\t%s\n", p2cstr(answerStr));
- }
- }
- } //• End of if(ThisButton())
- break;
- case 18:
- break;
- case 19:
- break;
- case 20: //• Help Button
- Help();
- break;
- case 21:
- break;
- case 22: //• E
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('E');
- break;
- case 23: //• Clear
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- HandleEditChoice(8); //• Select All
- HandleEditChoice(6); //• Clear
- }
- break;
- case 24: //• RAD/DEG toggle
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- if(gRad)
- {
- SetIText(itemH, "\pdeg"); //• use degrees for trig fxns
- gRad = false;
- }
- else
- {
- SetIText(itemH, "\prad"); //• use radians for trig fxns
- gRad = true;
- }
- }
- break;
- case 25: //• ()
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- BackIBeam();
- break;
- case 26: //• RCL
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- {
- strcpy(cStr1, p2cstr(memStr)); //• memStr is the calculator's memory.
- i=0;
- while(cStr1[i] != '\0')
- TypeIt(cStr1[i++]);
- c2pstr((char *)memStr);
- }
- break;
- case 27: //• M+
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- pStrCopy(answerStr, memStr);
- break;
- case 28: //• +
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('+');
- break;
- case 29: //• -
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('-');
- break;
- case 30: //• x
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('*');
- break;
- case 31: //• ÷
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('/');
- break;
- case 32: //• ^
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('^');
- break;
- case 33: //• %
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('%');
- break;
- case 34: //• .
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('.');
- break;
- case 35: //• 0
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('0');
- break;
- case 36: //• 1
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('1');
- break;
- case 37: //• 2
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('2');
- break;
- case 38: //• 3
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('3');
- break;
- case 39: //• 4
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('4');
- break;
- case 40: //• 5
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('5');
- break;
- case 41: //• 6
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('6');
- break;
- case 42: //• 7
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('7');
- break;
- case 43: //• 8
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('8');
- break;
- case 44: //• 9
- //• They clicked in this Rect!
- if(ThisButton(evp, &itemRect))
- TypeIt('9');
- break;
- default:
- break;
- } //• End switch
- }
- return 1;
- }
-
- //• DoUpdate() - pretty simple!
- void DoUpdate( EventRecord *eventPtr)
- {
- UpdateDialog(dialog, dialog->visRgn);
- }
-
- //• HandleMouseDown()
- void HandleMouseDown( EventRecord *eventPtr)
- {
- WindowPtr whichWindow;
- short thePart;
- long menuChoice;
-
- thePart = FindWindow( eventPtr->where, &whichWindow);
- switch( thePart)
- {
- case inMenuBar:
- menuChoice = MenuSelect( eventPtr->where);
- HandleMenuChoice( menuChoice);
- break;
- case inSysWindow:
- SystemClick( eventPtr, whichWindow);
- break;
- case inContent:
- break;
- case inDrag:
- DragWindow( whichWindow, eventPtr->where, &qd.screenBits.bounds);
- break;
- case inGoAway: //• Just quit if user clicks in GoAway box; this is just a simple program.
- if(TrackGoAway(whichWindow, eventPtr->where))
- gDone = true;
- break;
- }
- }
-
- //• BackIBeam()
- void BackIBeam(void)
- {
- EventRecord fakeEvt;
-
- TypeIt('(');
- TypeIt(')');
- //• Hmmm, this looks rather cryptic...
- fakeEvt.what = keyDown;
- fakeEvt.message = 162588;
- fakeEvt.modifiers = 128;
- doDlgEvt(&fakeEvt);
- }
-
- //• TypeIt()
- void TypeIt(char c)
- {
- EventRecord fakeEvt;
- long it;
-
- switch(c)
- {
- case 'a':
- it = 131169;
- break;
- case 'b':
- it = 133986;
- break;
- case 's':
- it = 131443;
- break;
- case 'c':
- it = 133219;
- break;
- case 'o':
- it = 139119;
- break;
- case 'i':
- it = 139881;
- break;
- case 'n':
- it = 142702;
- break;
- case 't':
- it = 135540;
- break;
- case 'h':
- it = 132200;
- break;
- case 'e':
- it = 134757;
- break;
- case 'x':
- it = 132984;
- break;
- case 'p':
- it = 140144;
- break;
- case 'l':
- it = 140652;
- break;
- case 'g':
- it = 132455;
- break;
- case 'q':
- it = 134257;
- break;
- case 'r':
- it = 135026;
- break;
- case '0':
- it = 138544;
- break;
- case '1':
- it = 135729;
- break;
- case '2':
- it = 135986;
- break;
- case '3':
- it = 136243;
- break;
- case '4':
- it = 136500;
- break;
- case '5':
- it = 137013;
- break;
- case '6':
- it = 136758;
- break;
- case '7':
- it = 137783;
- break;
- case '8':
- it = 138296;
- break;
- case '9':
- it = 137529;
- break;
- case '.':
- it = 143150;
- break;
- case '(':
- it = 137512;
- break;
- case ')':
- it = 138537;
- break;
- case 'E':
- it = 134725;
- break;
- case '*':
- it = 138282;
- break;
- case '+':
- it = 137259;
- break;
- case '-':
- it = 138029;
- break;
- case '/':
- it = 142383;
- break;
- case '^':
- it = 136798;
- break;
- case '%':
- it = 136997;
- break;
- default:
- DoError("\pStefan forgot to fix something!", false);
- break;
-
- }
- //• Hmmm, this looks rather cryptic...
- fakeEvt.what = keyDown;
- fakeEvt.message = it;
- fakeEvt.modifiers = 640; //• = Shift Key
- doDlgEvt(&fakeEvt);
- }
-
- //• Credits()
- void Credits(void)
- {
- short i;
-
- //• save current entry
- for(i=0; i<255; i++)
- saveStr[i] = expressionStr[i];
- DisposeDialog(dialog); //• Like I said, the main DLOG gets killed quite often...
- if(isPressed(58)) //• optionKey = 3A hex
- Alert(129, nil); //• Bonus easter egg!
- else
- Alert( 130, nil);
- DoMainDLOG(); //• ... and gets resurrected!
- }
-
- //• Help()
- void Help(void)
- {
- DisposeDialog(dialog); //• Like I said, the main DLOG gets killed quite often...
- Helper(); //• Here, refer to the separate file 'Help.c'
- DoMainDLOG(); //• ... and gets resurrected!
- }
-
- //• Again, my little secret!
- double Solve(char infixStr[])
- {
- double answer;
- long garbage;
- short i=0;
-
- while(infixStr[i] != '\0')
- garbage *= (int)infixStr[i++];
- answer = kPI * garbage;
- return answer;
- }
-
- void PleaseRegister(void)
- {
- switch (Alert(kPleaseRegisterAlertNum, 0L))
- {
- case 1:
- Registration();
- break;
- case 2: //• Cancel
- break;
- }
- }
-
- //• Registration()
- void Registration(void)
- {
- DialogPtr rDialog;
- Boolean done = false;
- Handle itemHandle;
- Rect itemRect;
- short itemType, itemHit;
- Handle okItemHandle, nameH, numH;
- Str255 nameStr, numStr;
- int code, i=0, j, l;
- short k;
-
- rDialog = GetNewDialog(kRegistrationDLOG, nil, (WindowPtr)-1L);
- ShowWindow(rDialog);
- SetPort(rDialog);
-
- GetDItem( rDialog, 1, &itemType, &okItemHandle, &itemRect);
- GetDItem( rDialog, 2, &itemType, &nameH, &itemRect);
- SelIText( rDialog, 2, kMinTextPosition, kMaxTextPosition);
- GetDItem( rDialog, 3, &itemType, &numH, &itemRect);
-
- SetDialogTracksCursor(rDialog, true);
- SetDialogDefaultItem(rDialog, ok);
-
- while(!done)
- {
- GetIText( nameH, nameStr);
- if( nameStr[0] == 0)
- HiliteControl((ControlHandle)okItemHandle, 255);
- else
- HiliteControl((ControlHandle)okItemHandle, 0);
- ModalDialog( nil, &itemHit);
- if(itemHit == ok)
- {
- GetDItem( rDialog, 2, &itemType, &nameH, &itemRect);
- GetIText( nameH, nameStr);
- j = strlen(p2cstr(nameStr));
- if(j < kMinNameLength)
- {
- DoError("\pThat name is invalid - too short!", false);
- goto skippy; //• Yuck, a 'goto' statement!
- }
- GetDItem( rDialog, 3, &itemType, &numH, &itemRect);
- GetIText( numH, numStr);
- l = strlen(p2cstr(numStr));
- if(j != l)
- {
- DoError("\pInvalid registration combination!", false);
- goto skippy;
- }
- //• I cut out my secret registration code here!
- DoError("\pInvalid registration combination!", false);
- goto skippy; //• Uh oh, another 'goto' statement!
- //• If you make it this far, you are registered!
- //• gRegistered = true;
- done = true;
- }
- }
- skippy:
- DisposeDialog(rDialog);
- }